package panda.server.util.trapfinder;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import panda.client.enumerations.MagicSet;
import panda.server.data.CardData;
import panda.server.data.MagicCardDB;

public class ManaPool {

	/* amount of mana in mana pool */
	private int white = 0, blue = 0, black = 0, red = 0, green = 0, generic = 0;

	public ManaPool() {
		zero();
	}

	public static void main(String[] args) throws IOException {
		ManaPool pool = new ManaPool();

		System.out.print("Mana cost: ");
		BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
		String input = in.readLine();

		int[] mana = new int[6];

		Pattern pattern = Pattern.compile("([0123456789X]?)([WUBRG]*)", Pattern.COMMENTS);
		Matcher matcher = pattern.matcher(input);

		if(matcher.find()) {

			String genericCost = matcher.group(1);

			if(genericCost.equals("")) {
				genericCost = "0";
			}

			mana[5] = Integer.parseInt(genericCost);

			String coloredCost = matcher.group(2);

			for(Character c : coloredCost.toCharArray()) {
				switch(c) {
					case 'W':
						mana[0]++;
						break;
					case 'U':
						mana[1]++;
						break;
					case 'B':
						mana[2]++;
						break;
					case 'R':
						mana[3]++;
						break;
					case 'G':
						mana[4]++;
						break;
					default:
						System.out.println("error :P");
				}
			}

			List<CardData> cards = MagicCardDB.getCardsFromSet(MagicSet.ZENDIKAR);
			cards.addAll(MagicCardDB.getCardsFromSet(MagicSet.WORLDWAKE));
			
			List<CardData> results = new ArrayList<CardData>();

			for(CardData card : cards) {
				boolean canCast = pool.canCast(card, mana);
				if(canCast) {
					results.add(card);
					System.out.println(card);
				}
			}
			
			Collections.sort(results, new Comparator<CardData>() {
				public int compare(CardData o1, CardData o2) {
					
					return 0;
				}
			});
		}
	}

	public boolean canCast(CardData card, int[] mana) {

		if(card.getType().contains("Land")) {
			/* if it's land, say you can't cast it. otherwise it will clog up search queries */
			return false;
		} else if(card.getType().contains("Instant")) {
			
			String castingCost;
			if(card.getType().contains("Trap")) {
				String body = card.getBodyText();
				Pattern pattern = Pattern.compile("you may pay ([0123456789X]?)([WUBRG]*) rather than pay");
				Matcher matcher = pattern.matcher(body.replace("{", "").replace("}", ""));
				
				if(matcher.find()) {
					// System.out.println(matcher.group(1) + matcher.group(2));
					castingCost = matcher.group(1) + matcher.group(2);
					
				} else {
					if(card.getName().equals("Stone Idol Trap")) {
						castingCost = "R";
					} else {
						throw new IllegalStateException();
					}
				}
				
				
			} else {
				castingCost = card.getCastingCost();
			}

			zero();

			white = mana[0];
			blue = mana[1];
			black = mana[2];
			red = mana[3];
			green = mana[4];
			generic = mana[5];

			Pattern pattern = Pattern.compile("([0123456789X]?)([WUBRG]*)", Pattern.COMMENTS);
			Matcher matcher = pattern.matcher(castingCost);

			if(matcher.find()) {
				// System.out.println(matcher.group(1) + ", " + matcher.group(2));

				String genericCost = matcher.group(1);

				if(genericCost.equals("")) {
					genericCost = "0";
				}
				String coloredCost = matcher.group(2);

				for(Character c : coloredCost.toCharArray()) {
					ManaColor color = ManaColor.GENERIC;
					switch(c) {
						case 'W':
							color = ManaColor.WHITE;
							break;
						case 'U':
							color = ManaColor.BLUE;
							break;
						case 'B':
							color = ManaColor.BLACK;
							break;
						case 'R':
							color = ManaColor.RED;
							break;
						case 'G':
							color = ManaColor.GREEN;
							break;
						default:
							System.out.println("error :P");
					}

					depleteColor(color);
				}

				if(isAnyColorDepleted()) {
					// System.out.println("white: " + white + " blue: " + blue + " black: " + black + " red: " + red +
					// " green: " + green);
					return false;
				} else {
					if(genericCost.equals("X")) {
						genericCost = "0";
					}
					if(getTotalManaAvailable() >= Integer.valueOf(genericCost)) {
						return true;
					}
				}

			} else {
				System.out.println("error, not found");
			}
		}
		return false;
	}

	private boolean isAnyColorDepleted() {
		if(white < 0 || blue < 0 || black < 0 || green < 0 || red < 0) {
			return true;
		} else
			return false;
	}

	private void depleteColor(ManaColor color) {
		switch(color) {
			case WHITE:
				white--;
				break;
			case BLUE:
				blue--;
				break;
			case BLACK:
				black--;
				break;
			case RED:
				red--;
				break;
			case GREEN:
				green--;
				break;
			case GENERIC:
				throw new IllegalArgumentException();
		}
	}

	public void addColor(ManaColor color) {
		switch(color) {
			case WHITE:
				white++;
				break;
			case BLUE:
				blue++;
				break;
			case BLACK:
				black++;
				break;
			case RED:
				red++;
				break;
			case GREEN:
				green++;
				break;
			case GENERIC:
				generic++;
				break;
		}
	}

	private void zero() {
		white = 0;
		blue = 0;
		black = 0;
		red = 0;
		green = 0;
		generic = 0;
	}

	private int getTotalManaAvailable() {
		return white + blue + black + red + green + generic;
	}

	/**
	 * Enumerates mana symbols for the colors of Magic: the Gathering. White, Blue, Black, Red, and Green.
	 * 
	 * @author zane.tian@gmail.com
	 */
	public enum ManaColor {
		WHITE("W"), BLUE("U"), BLACK("B"), RED("R"), GREEN("G"), GENERIC("~"); /* a dummy symbol */

		private String manaSymbol;

		private ManaColor(String symbol) {
			this.manaSymbol = symbol;
		}

		public String getColorCode() {
			return manaSymbol;
		}
	}
}